package cn.le.springAnnotationCustomize.context;

import cn.le.springAnnotationCustomize.annotation.CustomerValidator;
import cn.le.springAnnotationCustomize.annotationUtil.CustomerValidatorRule;
import cn.le.springAnnotationCustomize.annotationUtil.DateValidatorRule;
import org.eclipse.core.runtime.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by admin on 2017/3/31.
 * 使用自定义校验处理器
 */
@Component
public class CustomerValidatorFactory implements Validator
{
    @Autowired
    private CustomerValidatorConfig customerValidatorConfig;

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }

    @Override
    public void validate(Object target, Errors errors) {

        Assert.isNotNull(target);
        Assert.isNotNull(errors);
        //获取clazz bean所有的字段 Field对象
        List<Field> fields = getFields(target.getClass());
        for (Field field:fields) {
            //获取所在字段的Annotation
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation:annotations) {
                //判断其注解是否是自定义的注解类型
                if (annotation.annotationType().getAnnotation(CustomerValidator.class) != null) {
                    try {
                        DateValidatorRule customerValidatorRule = (DateValidatorRule) customerValidatorConfig
                                .findRule(annotation);
                        if (customerValidatorRule != null) {
                            customerValidatorRule.valid(annotation, target, field, errors);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

    /**
     * 获取clazz bean所有的字段 Field对象
     * @param clazz
     * @return
     */
    private List<Field> getFields(Class<? extends Object> clazz)
    {
        //声明Field数组
        List<Field> fields = new ArrayList<>();
        //如果class类型不为空
        while(clazz != null)
        {
            //clazz.getDeclaredFields返回Field对象,该对象反映了此class对象所表示的类或接口所声明的所以字段
            //添加属性到属性数组
            Collections.addAll(fields,clazz.getDeclaredFields());
            //返回表示class所表示的实体(类,接口,基本类型或void)的超类的class
            clazz = clazz.getSuperclass();
        }
        return fields;
    }
}
